﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//using iTextSharp.text;
//using iTextSharp.text.pdf;
//using iTextSharp.tool.xml;

namespace FreeDream.Common.FileConvert
{
    public class PdfConvertHelper
    {
        #region 1.多个PDF文件合并PDF 
        /// <summary>
        /// 读取合并的pdf文件名称
        /// </summary>
        /// <param name="Directorypath">目录</param>
        /// <param name="outpath">导出的路径</param>
        public static int MergePDF(string Directorypath, string outpath)
        {
            try
            {
                List<string> filelist2 = new List<string>();
                DirectoryInfo di2 = new DirectoryInfo(Directorypath);
                FileInfo[] ff2 = di2.GetFiles("*.pdf");
                BubbleSort(ff2);
                foreach (FileInfo temp in ff2)
                {
                    filelist2.Add(Directorypath + "\\" + temp.Name);
                }
                int totalpages = MergePdfFiles(filelist2, outpath);
                if (totalpages > 0)
                {
                    //DeleteAllPdf(Directorypath);
                }
                return totalpages;
            }
            catch (Exception e)
            {
                //QueenLogger.Error("MergePDF" + e.ToJson2());
                return 0;
            }



        }
        /// <summary>
        /// 排序文件，按创建时间（升序）
        /// </summary>
        /// <param name="arr">文件名数组</param>
        public static void BubbleSort(FileInfo[] arr)
        {
            for (int i = 0; i < arr.Length; i++)
            {
                for (int j = i; j < arr.Length; j++)
                {
                    if (arr[i].CreationTimeUtc > arr[j].CreationTimeUtc)//按创建时间（升序）
                    {
                        FileInfo temp = arr[i];
                        arr[i] = arr[j];
                        arr[j] = temp;
                    }
                }
            }
        }
        /// <summary>
        /// 合成PDF
        /// </summary>
        /// <param name="fileList"></param>
        /// <param name="outMergeFile"></param>
        /// <returns></returns>
        public static int MergePdfFiles(List<string> fileList, string outMergeFile)
        {
            int totalPage = 0;
            PdfReader reader;
            List<PdfReader> readerList = new List<PdfReader>();
            Document document = new Document();
            PdfWriter writer = PdfWriter.GetInstance(document, new FileStream(outMergeFile, FileMode.Create));
            document.Open();
            PdfContentByte cb = writer.DirectContent;
            PdfImportedPage newPage;
            for (int i = 0; i < fileList.Count; i++)
            {
                reader = new PdfReader(fileList[i]);
                int iPageNum = reader.NumberOfPages;
                totalPage += iPageNum;
                for (int j = 1; j <= iPageNum; j++)
                {
                    document.NewPage();
                    newPage = writer.GetImportedPage(reader, j);
                    cb.AddTemplate(newPage, 0, 0);
                }
                readerList.Add(reader);
            }
            document.Close();
            foreach (var rd in readerList)//清理占用
            {
                rd.Dispose();
            }

            return totalPage;
        }


        /// <summary>
        /// 删除一个文件里所有的文件
        /// </summary>
        /// <param name="Directorypath">文件夹路径</param>
        public static void DeleteAllPdf(string Directorypath)
        {
            DirectoryInfo di = new DirectoryInfo(Directorypath);
            if (di.Exists)
            {
                FileInfo[] ff = di.GetFiles("*.pdf");
                foreach (FileInfo temp in ff)
                {
                    File.Delete(Directorypath + "\\" + temp.Name);
                }
            }
        }
        #endregion

        #region 2.0 Html生成Pdf
        /// <summary>
        /// html转pdf
        /// </summary>
        /// <param name="qrnlist"></param>
        /// <param name="path"></param>
        public static void HtmlStrToPdf(string htmltext, string fullpath)
        {
            string text = htmltext;
            MemoryStream outputStream = new MemoryStream();//要把PDF写到哪个串流
            byte[] data = System.Text.Encoding.UTF8.GetBytes(text);//字串转成byte[]
            MemoryStream msInput = new MemoryStream(data);
            Document doc = new Document();//要写PDF的文件，建构子没填的话预设直式A4
            PdfWriter writer = PdfWriter.GetInstance(doc, outputStream);
            //指定文件预设开档时的缩放为100%
            PdfDestination pdfDest = new PdfDestination(PdfDestination.XYZ, 0, doc.PageSize.Height, 1f);
            //开启Document文件
            doc.Open();
            //使用XMLWorkerHelper把Html parse到PDF档里
            XMLWorkerHelper.GetInstance().ParseXHtml(writer, doc, msInput, null, Encoding.UTF8, new UnicodeFontFactory());
            //将pdfDest设定的资料写到PDF档
            PdfAction action = PdfAction.GotoLocalPage(1, pdfDest, writer);
            writer.SetOpenAction(action);
            doc.Close();
            msInput.Close();
            outputStream.Close();
            //回传PDF档案 
            var bytes = outputStream.ToArray();
            var ret = System.Convert.ToBase64String(bytes);

            string strbase64 = ret;
            strbase64 = strbase64.Replace(' ', '+');
            System.IO.MemoryStream stream = new System.IO.MemoryStream(Convert.FromBase64String(strbase64));
            //"D:\\Download\\证件1.pdf"
            System.IO.FileStream fs = new System.IO.FileStream(fullpath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
            byte[] b = stream.ToArray();
            fs.Write(b, 0, b.Length);
            fs.Close();

        }
        public static string HtmlSaveToPdf(string htmltext, string businessType = "PDF")
        {
            #region 
            string relativePath = Path.Combine("upload", businessType, $"{DateTime.Now:yyyyMMdd}");
            var outprintfilename = Guid.NewGuid().ToString("N");
            var outputpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, relativePath, $"{outprintfilename}.pdf");
            var htmlString = @"<html>
 <body>
  Hello World from ddd.com.
 </body>
</html>
";
            HtmlStrToPdf(htmlString, outputpath);
            return Path.Combine(relativePath, $"{outprintfilename}.pdf");
            #endregion
        }
        #endregion

        #region 3.0 图片合成pdf

        public static string jpgs2pdf(string filepath, ref int cnt)
        {
            DirectoryInfo di2 = new DirectoryInfo(filepath);
            FileInfo[] ff2 = di2.GetFiles("*.jpg");
            BubbleSort(ff2);
            List<string> imgdic = new List<string>();
            foreach (FileInfo temp in ff2)
            {
                if (!temp.Name.Contains("签名"))
                {
                    imgdic.Add(temp.FullName);
                }
            }
            string pdfpath = filepath + "outjpgs.pdf";
            cnt = imgs2Pdf(imgdic, pdfpath);
            return pdfpath;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="files">图片路径集合</param>
        /// <param name="newpdfpath">输出pdf的路径</param>
        public static int imgs2Pdf(List<string> files, string newpdfpath)
        {
            Document document = new Document(PageSize.A4, 25, 25, 25, 25);
            int totolpage = 0;
            try
            {
                PdfWriter.GetInstance(document, new FileStream(newpdfpath, FileMode.Create, FileAccess.ReadWrite));
                document.Open();
                Image image;
                for (int i = 0; i < files.Count; i++)
                {
                    if (string.IsNullOrEmpty(files[i])) break;
                    image = Image.GetInstance(files[i]);
                    if (image.Height > PageSize.A4.Height - 25)
                    {
                        image.ScaleToFit(PageSize.A4.Width - 25, PageSize.A4.Height - 25);
                    }
                    else if (image.Width > PageSize.A4.Width - 25)
                    {
                        image.ScaleToFit(PageSize.A4.Width - 25, PageSize.A4.Height - 25);
                    }
                    image.Alignment = Element.ALIGN_MIDDLE;
                    //image.SetDpi(72, 72); 
                    document.NewPage();
                    document.Add(image);
                    totolpage++;
                }
            }
            catch (Exception ex)
            {
            }
            if (document.IsOpen())
            {
                document.Close();
            }
            return totolpage;
        }
        #endregion

        #region 4.0 pdf转img 
        /// <summary>
        /// 主要使用这个转换img
        /// </summary>
        /// <param name="pdfPath">pdf的文件路径</param>
        /// <param name="outputPath">输出jpg的文件路径</param>
        /// <param name="imgFileName">输出jpg的文件名称</param>
        /// <returns></returns>
        public static List<System.Drawing.Image> RenderPages(string pdfPath, string outputPath, string imgFileName = null)
        {
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }
            imgFileName = imgFileName ?? Guid.NewGuid().ToString();
            var images = new List<System.Drawing.Image>();
            var pdf = PdfiumViewer.PdfDocument.Load(pdfPath);
            var pdfPage = pdf.PageCount;
            var pageSizes = pdf.PageSizes;

            for (int i = 1; i <= pdfPage; i++)
            {
                System.Drawing.Size size = new System.Drawing.Size { Height = (int)pageSizes[i - 1].Height, Width = (int)pageSizes[i - 1].Width };
                images.Add(RenderPage(pdfPath, i, size, $"{outputPath}{imgFileName}-{i}.jpg"));
            }
            return images;
        }

        /// <summary>
        /// 将PDF转换为图片
        /// </summary>
        /// <param name="pdfPath">pdf文件位置</param>
        /// <param name="pageNumber">pdf文件张数</param>
        /// <param name="size">pdf文件尺寸</param>
        /// <param name="outputPath">输出图片位置与名称</param>
        public static System.Drawing.Image RenderPage(string pdfPath, int pageNumber, System.Drawing.Size size, string outputPath, int dpi = 300)
        {
            System.Drawing.Image temp;
            using (var document = PdfiumViewer.PdfDocument.Load(pdfPath))
            using (var stream = new FileStream(outputPath, FileMode.Create))
            //using(var image = GetPageImage(pageNumber, size, document, dpi))
            {
                var image = GetPageImage(pageNumber, size, document, dpi);
                image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                return image;
            }
        }

        /// <summary>
        /// 将PDF转换为图片
        /// </summary>
        /// <param name="pdfPath"></param>
        /// <param name="pageNumber">pdf文件张数 1开始</param>
        /// <param name="size"></param>
        /// <param name="outputPath"></param>
        /// <param name="dpi"></param>
        /// <returns></returns>
        public static System.Drawing.Image GetPageImageByPdfPath(string pdfPath, int pageNumber = 1, int dpi = 300)
        {
            //System.Drawing.Image temp;
            using (var pdf = PdfiumViewer.PdfDocument.Load(pdfPath))
            //using (var stream = new FileStream(outputPath, FileMode.Create))
            //using(var image = GetPageImage(pageNumber, size, document, dpi))
            {
                var pdfPage = pdf.PageCount;
                if (pdfPage < pageNumber)
                {
                    return null;
                }
                var pageSizes = pdf.PageSizes;
                System.Drawing.Size size = new System.Drawing.Size { Height = (int)pageSizes[pageNumber - 1].Height, Width = (int)pageSizes[pageNumber - 1].Width };
                var image = GetPageImage(pageNumber, size, pdf, dpi);
                //image.Save(stream, System.Drawing.Imaging.ImageFormat.Jpeg);
                return image;
            }
        }

        private static System.Drawing.Image GetPageImage(int pageNumber, System.Drawing.Size size, PdfiumViewer.PdfDocument document, int dpi)
        {
            return document.Render(pageNumber - 1, size.Width, size.Height, dpi, dpi, PdfRenderFlags.Annotations);
        }



        #endregion

        #region 5.0 PDF 拆分
        public static List<string> SplitAndSave(string inputPath, string outputPath)
        {
            FileInfo file = new FileInfo(inputPath);
            List<string> fileList = new List<string>();
            string name = file.Name.Substring(0, file.Name.LastIndexOf(".", StringComparison.Ordinal));
            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }
            using (PdfReader reader = new PdfReader(inputPath))
            {
                for (int pageIndex = 1; pageIndex <= reader.NumberOfPages; pageIndex++)
                {
                    string filename = $"{name}-{pageIndex}.pdf";
                    Document document = new Document();
                    PdfCopy copy = new PdfCopy(document, new FileStream(outputPath + "\\" + filename, FileMode.Create));
                    document.Open();
                    copy.AddPage(copy.GetImportedPage(reader, pageIndex));
                    document.Close();
                    fileList.Add(outputPath + "\\" + filename);
                }
            }

            return fileList;
        }


        #endregion
    }
    /// <summary>
    /// 自定义字体
    /// </summary>
    public class UnicodeFontFactory : FontFactoryImp
    {
        private static readonly string arialFontPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts),
            "arialuni.ttf");//arial unicode MS是完整的unicode字型。
        private static readonly string _Path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Fonts),
            "KAIU.TTF");//標楷體


        public override Font GetFont(string fontname, string encoding, bool embedded, float size, int style, BaseColor color,
            bool cached)
        {
            //可用Arial或標楷體，自己選一個
            BaseFont baseFont = BaseFont.CreateFont(arialFontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            return new Font(baseFont, size, style, color);
        }
    }


    /// <summary>
    /// 自定义图片的清晰度，数字越大越清晰
    /// </summary>
    public enum Definition
    {
        One = 1, Two = 2, Three = 3, Four = 4, Five = 5, Six = 6, Seven = 7, Eight = 8, Nine = 9, Ten = 10
    }
}
